/*
 * Copyright 2009 Zero Separation
 *
 *     This file is part of PDSUtilities.
 *
 *  PDSUtilities is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  PDSUtilities is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with PDSUtilities.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package com.zero_separation.pds.utilities.referencecollections;

import java.util.Collection;
import java.util.List;
import java.util.ListIterator;

/**
 * This is an abstract implementation of a List that will automatically
 * reference and dereference ManagedObjects placed inside. In order to create
 * a new fully featured ReferenceCollection with a different storage mechanism
 * just extend this class and implement the abstract method along with whichever
 * constructors are required.
 *
 * @author Tim Boura - Zero Separation
 */
public abstract class ReferenceAbstractList<T> extends ReferenceAbstractCollection<T, List> implements List<T> {
    /** The version of the serialized form of this class. */
    private static final long serialVersionUID = 1L;

    public boolean addAll(int index, Collection<? extends T> c) {
        for (T o: c)
            add(index, o);
        return c.size()>0;
    }

    public T get(int index) {
        Object o = getInternalCollection().get(index);
        return (T)dereferenceIfNeeded(o);
    }

    public T set(int index, T element) {
        return (T)dereferenceIfNeeded(getInternalCollection().set(index, referenceIfNeeded(element)));
    }

    public T remove(int index) {
        return (T)dereferenceIfNeeded(getInternalCollection().remove(index));
    }

    public int indexOf(Object o) {
        return getInternalCollection().indexOf(referenceIfNeeded(o));
    }

    public int lastIndexOf(Object o) {
        return getInternalCollection().lastIndexOf(referenceIfNeeded(o));
    }

    public ListIterator<T> listIterator() {
        return new ReferenceListIterator<T>(getInternalCollection().listIterator());
    }

    public ListIterator<T> listIterator(int index) {
        return new ReferenceListIterator<T>(getInternalCollection().listIterator(index));
    }

    public List<T> subList(int fromIndex, int toIndex) {
        return new ReferenceSubList<T>(getInternalCollection().subList(fromIndex, toIndex));
    }

    public void add(int index, T element) {
        getInternalCollection().add(index, referenceIfNeeded(element));
    }

}
